﻿using GSBA.Common;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;

namespace GSBA.ViewModels
{
    /// <summary>
    /// View model for MainPage
    /// </summary>
    public class MainPageViewModel : ViewModelBase
    {
        private static IList<string> tileBackgroundResources;

        static MainPageViewModel()
        {
            tileBackgroundResources = new List<string>() {
                "MainPageTile_Blue", "MainPageTile_Green", "MainPageTile_Yellow", "MainPageTile_Pink", "MainPageTile_Grey", "MainPageTile_Purple"
            };
        }

        public MainPageViewModel()
            : base()
        {
            this.InstantiateStaticNavigationElements();
        }

        protected override void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
        }

        private NavigationItem selectedCategory;
        public NavigationItem SelectedCategory
        {
            get
            {
                return selectedCategory;
            }
            set
            {
                selectedCategory = value;
                selectedCategory.ItemCommand.Execute(this);
            }
        }

        private static IReadOnlyList<Windows.Storage.StorageFile> Files = null;
        private int lastReadIndex = 0;

        private async Task PopulateData()
        {
            this.IsCategoryLoading = true;

            var stopwatch = Stopwatch.StartNew();
            Debug.WriteLine("Populate Data: {0}", stopwatch.ElapsedMilliseconds);
            if (Files == null)
            {
                var storageFolder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync(System.IO.Path.Combine("Data", "Category"));
                Debug.WriteLine("Loaded Folder: {0}", stopwatch.ElapsedMilliseconds);
                Files = await storageFolder.GetFilesAsync();
            }
            Debug.WriteLine("Loaded Files: {0}", stopwatch.ElapsedMilliseconds);

            var filesCount = Files.Count;

            var category = new NavigationCategory(1, "Directory");

            var items = new ObservableCollection<NavigationItem>();

            for (int i = 0; i < Files.Count; i++)
            {
                var file = Files[i];
                int lastFileSeparator = file.Path.LastIndexOf('\\');
                var categoryName = file.Path.Substring(lastFileSeparator + 1, file.Path.LastIndexOf('.') - lastFileSeparator - 1).Replace("_", " ");
                NavigationItem item;
                item = new NavigationItem(categoryName, "", "", tileBackgroundResources[i % tileBackgroundResources.Count], category);
                item.ItemCommand = new NavigationCommand<object>((o) => NavigationService.GetInstance().Navigate("CategoryListing", new object[] { categoryName, file }));
                items.Add(item);
            }

            this.IsCategoryLoading = false;

            Debug.WriteLine("Created Category Items: {0}", stopwatch.ElapsedMilliseconds);

            this.Items = items; // new ObservableCollection<NavigationItem>(items);
            Debug.WriteLine("Set Category Items: {0}", stopwatch.ElapsedMilliseconds);
            stopwatch.Stop();
            /*new PaginatedCollection<NavigationItem>(() => { return Files.Count == 0 || lastReadIndex < Files.Count; }, (uint count) =>
            {
                Func<Task<LoadMoreItemsResult>> taskFunc = async () =>
                {
                    int readLimit = lastReadIndex + 2;
                    await Task.Delay(5);
                    for (int i = lastReadIndex; i < Files.Count && i <= readLimit; ++i)
                    {
                        var file = Files[i];
                        int lastFileSeparator = file.Path.LastIndexOf('\\');
                        var categoryName = file.Path.Substring(lastFileSeparator + 1, file.Path.LastIndexOf('.') - lastFileSeparator - 1);
                        NavigationItem item;
                        if (!cachedNavigationItems.ContainsKey(categoryName))
                        {
                            item = new NavigationItem(categoryName, "", "", tileBackgroundResources[i % tileBackgroundResources.Count], category);
                            cachedNavigationItems.Add(categoryName, item);
                        }
                        else
                        {
                            item = cachedNavigationItems[categoryName];
                        }
                        item.ItemCommand = new NavigationCommand<object>((o) => NavigationService.GetInstance().Navigate("CategoryListing", new object[] { categoryName, file }));
                    this.Items.Add(item);
                    }

                    lastReadIndex = ++readLimit;

                    return new LoadMoreItemsResult()
                    {
                        Count = (uint)lastReadIndex
                    };
                };
                Task<LoadMoreItemsResult> loadMorePostsTask = taskFunc();
            return loadMorePostsTask.AsAsyncOperation<LoadMoreItemsResult>();
        });*/
        }

        /// <summary>
        /// Instantiate the navigation items for the main page
        /// </summary>
        private async void InstantiateStaticNavigationElements()
        {
            this.TimeCounter = "Loading...";

            if (!Windows.ApplicationModel.DesignMode.DesignModeEnabled)
            {
                await PopulateData();
            }
            else
            {
                this.Items = new ObservableCollection<NavigationItem>();
                // There are lots of TODOs here to replace the string, image resource path
                var category = new NavigationCategory(1, "Directory");

                for (int i = 1; i != 100; ++i)
                {
                    var categoryName = "Category " + i;
                    var item = new NavigationItem(categoryName, "", "", tileBackgroundResources[i % tileBackgroundResources.Count], category);
                    item.ItemCommand = new NavigationCommand<object>((o) => NavigationService.GetInstance().Navigate("CategoryListing", categoryName));
                    this.Items.Add(item);
                }
            }

            IsCategoryLoadingCompleted = true;
        }

        void OnRefresh(object obj)
        {
        }

        private ObservableCollection<NavigationItem> items;
        public ObservableCollection<NavigationItem> Items
        {
            get
            {
                return items;
            }
            set
            {
                items = value;
                RaisePropertyChanged("Items");
            }
        }

        public string TimeCounter
        {
            get;
            set;
        }

        private bool isCategoryLoadingCompleted = false;
        public bool IsCategoryLoadingCompleted
        {
            get
            {
                return isCategoryLoadingCompleted;
            }
            set
            {
                isCategoryLoadingCompleted = value;
                RaisePropertyChanged("IsCategoryLoadingCompleted");
            }
        }

        public bool IsCategoryLoading
        {
            get
            {
                return !this.isCategoryLoadingCompleted;
            }
            set
            {
                this.isCategoryLoadingCompleted = !value;
                RaisePropertyChanged("IsCategoryLoading");
                RaisePropertyChanged("IsCategoryLoadingCompleted");
            }
        }
    }
}
